#include "mlib_NixietubeDrive.h"

const uint8 display_value[] =
    {
        // 0-9:'0'-'9'
        0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,
        // 10-19:'0.'-'9.'
        0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10,
        0x00, // 20  	OFF
        0x77, // 21   A
        0x39, // 22   C
        0x79, // 23   E
        0x71, // 24   F
        0x76, // 25   H
        0x38, // 26   L
        0x73, // 27   P
        0x3E, // 28   U
        0x80, // 29   ?
        0x40, // 30  '-'
              //
        0xFF, // 31   ALL ON
        0xfd, // 32   DB
        0xfb, // 33   DC
        0xf7, // 34   DD
        0xef, // 35   DE
        0xdf, // 36   DF
        0xbf, // 37   DG
        0x7f, // 38   DH
        0x5E, // 39   d
        0xc0, // 40
        0xf9, // 41
        0xa4, // 42
        0xb0, // 43
        0x99, // 44
        0x92, // 45
        0x82, // 46
        0xf8, // 47
        0x80, // 48
        0x90, // 49
};

#define LED_K3_FUNNAME_VALUE 39 // 特殊的灯

/*
初始化数码管

hardwareInit    ：初始化数码管底层硬件IO函数指针
myobject        ：数码管对象指针

*/
// void mlib_Nixietube_init(void(* hardwareInit)(void),MLIB_NIXIETUBE_OBJECT_S *myobject)
void mlib_Nixietube_init(MLIB_NIXIETUBE_OBJECT_S *myobject)
{
    // if(hardwareInit)hardwareInit();
    mlib_Nixietube_Object_DefaulInit(myobject);
    myobject->scan_nowsit = 0;
    myobject->scan_state = 0;
    myobject->time_ms = 0;
}

/*
缺省初始化数码管对象
myobject    ：数码管对象指针
*/
void mlib_Nixietube_Object_DefaulInit(MLIB_NIXIETUBE_OBJECT_S *myobject)
{
    myobject->scan_nowsit = 0;
    myobject->scan_state = 0;
    myobject->time_ms = 0;
    //
    myobject->type_enum = MLIB_NIXIETUBE_SEG8_GENERAL;
    myobject->bit_count = 2;
    myobject->bit_enable_level = 1; // 0
    myobject->seg_enable_level = 1; // 1
    myobject->lum_level_max = 0;    // 灭灯时间，最大亮度等级
    myobject->lum_level = 2;        // 亮灯时间，当前亮度
    myobject->dis_buff.seg8_general[0] = display_value[0];
    myobject->dis_buff.seg8_general[1] = display_value[1];
    myobject->dis_buff.seg8_general[2] = display_value[2];
    myobject->dis_buff.seg8_general[3] = display_value[3];
    myobject->dis_buff.seg8_general[4] = display_value[4];
    myobject->dis_buff.seg8_general[5] = display_value[5];
    myobject->dis_buff.seg8_general[6] = display_value[6];
    myobject->dis_buff.seg8_general[7] = display_value[7];
}

/*
数码管扫描函数，需要按照一定的周期调用此函数

myobject:数码管对象，不同的数码管传递不同的对象
bitOutput：数码管位扫描输出函数指针
            index表示位的编号，从0开始
            state表示位控制IO的输出状态
segOutput：数码管段赋值，segvalue为需要赋值的值，最大只支持16段的数码管
*/
void mlib_Nixietube_Scan(MLIB_NIXIETUBE_OBJECT_S *myobject,
                         void (*bitOutput)(uint8 index, uint8 state),
                         void (*segOutput)(uint16 segvalue))
{
    if (myobject->time_ms > 0)
        myobject->time_ms--;
    //
    if (myobject->scan_state == 0) // 使能位
    {
        if (myobject->time_ms > 0)
            return;
        // 使能位输出
        if (segOutput)
            segOutput(myobject->dis_buff.seg8_general[myobject->scan_nowsit]);
        // 使能段输出
        if (bitOutput)
            bitOutput(myobject->scan_nowsit, myobject->bit_enable_level);
        myobject->time_ms = myobject->lum_level;
        myobject->scan_state = 1;
    }
    else // 失能位
    {
        if (myobject->time_ms > 0)
            return;

        // 关闭位码
        if (bitOutput)
            bitOutput(myobject->scan_nowsit, !myobject->bit_enable_level);

        // 关闭段码
        if (segOutput)
        {
            if (myobject->seg_enable_level == 0)
            {
                segOutput(0xFFFF);
            }
            else
            {
                segOutput(0x0000);
            }
        }

        myobject->time_ms = myobject->lum_level_max;
        myobject->scan_state = 0;
        //
        myobject->scan_nowsit++;
        if (myobject->scan_nowsit >= myobject->bit_count)
        {
            myobject->scan_nowsit = 0;
        }
    }
}

/*
指定数码管某一位显示数字
myobject    :数码管对象
sit         :指定数码管位置，从0开始
number      :指定显示指定的数字，0-9纯数字,10-19表示带小数点的数字
*/
void mlib_Nixietube_Sit_DisplayNumber(MLIB_NIXIETUBE_OBJECT_S *myobject, uint8 sit, uint8 number)
{
    if (myobject->type_enum == MLIB_NIXIETUBE_SEG8_GENERAL)
    {
        if (sit >= myobject->bit_count)
            return;
        myobject->dis_buff.seg8_general[sit] = display_value[number];
    }
}

/*
将数码管作为一个整体，然后将一个有符号整形数据显示到数码管上
myobject    :数码管对象指针
value       :要显示的值
*/
void mlib_Nixietube_DisplayInt16(MLIB_NIXIETUBE_OBJECT_S *myobject, int16 value)
{
    uint8 i;
    uint8 max = myobject->bit_count;
    uint8 minus = 0;
    if (value < 0)
    {
        if (value / 10 != 0) // 2位负数将seg8_general[0]bit7加负号，
        {
            minus = 1;
        }
        else
        {
            max = myobject->bit_count - 1; // 1 位负数执行正常流程
        }
        value *= -1;
    }
    if (value >= 0)
    {
        for (i = 0; value > 0 && i < max;)
        {
            if (minus && i == 0) // 2位负数将seg8_general[0]bit7加负号，
            {
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[value % 10] | 0x80;
            }
            else
            {
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[value % 10]; // 这个地方反向了，把个为放在了1，十位放在了0，造成数据扫描时候也需要反向一下10位和个位换个位置
            }
            i++;
            value /= 10;
        }
        if (i == 0)
        {
            i = 1;
            myobject->dis_buff.seg8_general[myobject->bit_count - 1] = display_value[0];
        }
        else
        {
            // if (minus) //
            if (max == myobject->bit_count - 1)
            {
                i = 1;
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[30];
                // myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] |= 0x80;
                i++;
            }
        }
        for (; i < myobject->bit_count; i++)
        {
            myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[20];
        }
    }
}

void mlib_Nixietube_DisplayInt16Mode2(MLIB_NIXIETUBE_OBJECT_S *myobject, int16 value) // 十位补零
{
    uint8 i;
    uint8 max = myobject->bit_count;
    uint8 minus = 0;
    if (value < 0)
    {
        if (value < 0) // 2位负数将seg8_general[0]bit7加负号，
        {
            minus = 1;
        }
        // else
        // {
        //     max = myobject->bit_count - 1; // 1 位负数执行正常流程
        // }
        value *= -1;
    }
    if (value >= 0)
    {
        for (i = 0; i <= 1 && i < max;)
        {
            if (minus && i == 0) // 2位负数将seg8_general[0]bit7加负号，
            {
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[value % 10] | 0x80;
            }
            else
            {
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[value % 10]; // 这个地方反向了，把个为放在了1，十位放在了0，造成数据扫描时候也需要反向一下10位和个位换个位置
            }
            i++;
            value /= 10;
        }
        if (i == 0)
        {
            i = 1;
            myobject->dis_buff.seg8_general[myobject->bit_count - 1] = display_value[0];
        }
        else
        {
            // if (minus) //
            if (max == myobject->bit_count - 1)
            {
                i = 1;
                myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[30];
                // myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] |= 0x80;
                i++;
            }
        }
        for (; i < myobject->bit_count; i++)
        {
            myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[20];
        }
    }
}

/*
将数码管作为一个整体，然后将一个无符号整形数据显示到数码管上
myobject    :数码管对象指针
value       :要显示的值
*/
void mlib_Nixietube_DisplayUint16(MLIB_NIXIETUBE_OBJECT_S *myobject, uint16 value)
{
    uint8 i;
    if (myobject->type_enum == MLIB_NIXIETUBE_SEG8_GENERAL)
    {
        for (i = 0; value > 0 && i < myobject->bit_count;)
        {
            myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[value % 10];
            i++;
            value /= 10;
        }
        if (i == 0)
        {
            i = 1;
            myobject->dis_buff.seg8_general[myobject->bit_count - 1] = display_value[0];
        }
        for (; i < myobject->bit_count; i++)
        {
            myobject->dis_buff.seg8_general[myobject->bit_count - 1 - i] = display_value[20];
        }
    }
}

/*
从指定位置显示固定位数的整形数据，没有数据的位置显示0
myobject    :数码管对象指针
startSit    :显示起始位置
value       :要显示的值
maxSit      ：显示最大位数
*/
void mlib_Nixietube_DisplayUint16_Custom(MLIB_NIXIETUBE_OBJECT_S *myobject, uint8 startSit, uint16 value, uint8 maxSit)
{
    if (myobject->type_enum == MLIB_NIXIETUBE_SEG8_GENERAL)
    {
        if (startSit >= myobject->bit_count)
            return;
        for (; maxSit > 0; maxSit--)
        {
            if (startSit + maxSit - 1 < myobject->bit_count)
            {
                myobject->dis_buff.seg8_general[startSit + maxSit - 1] = display_value[value % 10];
            }
            value /= 10;
        }
    }
}

/*
将数码管作为一个整体，然后将一个浮点型数据显示到数码管上
myobject    :数码管对象指针
value       :要显示的值
point       :指定显示小数点位数
*/
void mlib_Nixietube_DisplayFloat(MLIB_NIXIETUBE_OBJECT_S *myobject, float value, uint8 point)
{
    uint8 max_sit = myobject->bit_count;
    uint8 buff;
    uint8 i;
    uint16 value2;
    uint8 max = max_sit;
    for (i = point; i > 0; i--)
    {
        value *= 10;
    }
    if (value < 0)
    {
        value *= -1;
        max = max_sit - 1;
    }
    //
    value2 = (uint16)value;
    for (i = 0; value2 > 0 && i < max;)
    {
        buff = value2 % 10;
        if (i != 0 && i == point)
            myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[buff + 10];
        else
        {
            myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[buff];
        }
        i++;
        value /= 10;
        value2 = (uint16)value;
    }
    if (i == 0)
    {
        i = 1;
        myobject->dis_buff.seg8_general[max_sit - 1] = display_value[0];
    }
    else
    {
        for (; i < point; i++)
        {
            myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[0];
        }
        if (i == point)
        {
            myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[10];
            i++;
        }
        if (max == max_sit - 1)
        {
            myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[30];
            i++;
        }
    }
    for (; i < max_sit; i++)
    {
        myobject->dis_buff.seg8_general[max_sit - 1 - i] = display_value[20];
    }
}

/*
设置数码管亮度等级
myobject    :数码管对象指针
value       :亮度等级值
*/
void mlib_Nixietube_lum_level_set(MLIB_NIXIETUBE_OBJECT_S *myobject, uint16 value)
{
    myobject->lum_level = value;
}
